#include <assert.h>
#include "Common.h"



// ============================ FreeList ============================
void FreeList::Push(void* obj)
{
	NextObj(obj) = m_freeList;
	m_freeList = obj;
	++m_size;
}

//弹出对象 头删
void* FreeList::Pop()
{
	assert(m_freeList);
	void* ptr = m_freeList;
	//m_freeList = *(void**)m_freeList;
	m_freeList = NextObj(ptr);
	--m_size;
	return ptr;
}

//头插一段链表
void FreeList::PushRange(void* start, void* end, size_t n)
{
	NextObj(end) = m_freeList;
	m_freeList = start;
	++m_size;
}

//头删一段链表
void FreeList::PopRange(void*& start, void*& end, size_t n)
{
	assert(n >= m_size);

	start = m_freeList;
	end = start;

	for (size_t i = 0; i < n - 1; ++i)
	{
		end = NextObj(end);
	}
	m_freeList = NextObj(end);
	NextObj(end) = nullptr;

	m_size -= n;
}

// ============================ FreeList ============================


// ============================ SizeClass ============================

//根据对象大小的对齐映射规则 计算内存大小
size_t SizeClass::RoupdUp(size_t size)
{
	if (size <= 128)
	{
		return _RoundUp(size, 8);
	}
	else if (size <= 1024)
	{
		return _RoundUp(size, 16);
	}
	else if (size <= 8 * 1024)
	{
		return _RoundUp(size, 128);
	}
	else if (size <= 64 * 1024)
	{
		return _RoundUp(size, 1024);
	}
	else if (size <= 256 * 1024)
	{
		return _RoundUp(size, 8 * 1024);
	}
	else
	{
		return _RoundUp(size, 1 << PAGE_SHIFT); //按照一个页的大小内存对齐
	}
	return size_t();
}

//根据对象大小的对齐映射规则 计算内存大小
size_t SizeClass::_RoundUp(size_t bytes, size_t alignNum)
{
	size_t alignSize = 0;
	if (bytes % alignNum != 0)
	{
		alignSize = (bytes / alignNum + 1) * alignNum;
	}
	else
	{
		alignSize = bytes;
	}
	return alignSize;

	//return ((bytes + alignNum - 1) & ~(alignNum - 1));
}

//计算映射到哪一个自由链表通
size_t SizeClass::Index(size_t bytes)
{
	//断言size<=256KB
	assert(bytes <= MAX_BYTES);

	//每个区间有多少个链
	static int group_array[5] = { 16, 56, 56, 56, 24 };
	if (bytes <= 128)
	{
		return _Index(bytes, 3); //8  2^3  每增长8个字节为一个链
	}
	else if (bytes <= 1024)
	{
		return _Index(bytes - 128, 4) + group_array[0];//把前面128减掉，再加上前一个桶的数量
	}
	else if (bytes <= 8 * 1024)
	{
		return _Index(bytes - 1024, 7) + group_array[1] + group_array[0];
	}
	else if (bytes <= 64 * 1024)
	{
		return _Index(bytes - 8 * 1024, 10) + group_array[2] + group_array[1] + group_array[0];
	}
	else if (bytes <= 256 * 1024)
	{
		return _Index(bytes - 64 * 1024, 13) + group_array[3] + group_array[2] + group_array[1] + group_array[0];
	}
	else
	{
		assert(false);
	}

	return - 1;
}

size_t SizeClass::_Index(size_t bytes, size_t alignNum)
{
	return (bytes >> alignNum) - 1;

	//size_t shifted_bytes = bytes + (1 << alignNum) - 1;
	//size_t shifted_bits = shifted_bytes >> alignNum;
	//return shifted_bits - 1;

	//return ((bytes + (1 << alignNum) - 1) >> alignNum) - 1;
}


//thread cache 一次从中心缓存获取多少个对象
size_t SizeClass::NumMoveSize(size_t size)
{
	assert(size > 0);

	//计算一次批量移动多少个对象的(慢启动)上限值  [2 , 522]
	int num = MAX_BYTES / size;
	if (num < 2) num = 2;
	if (num > 512) num = 512;

	return num;
}

// 计算一次向系统获取几个页
size_t SizeClass::NumMovePage(size_t size)
{
	size_t num = NumMoveSize(size);
	size_t nPage = num * size;
	nPage >>= PAGE_SHIFT;

	if (nPage == 0) nPage = 1;

	return nPage;
}


// ============================ SizeClass ============================




// ============================ SpanList ============================

SpanList::SpanList()
{
	//初始化表头
	m_head = new Span;
	m_head->next = m_head->prev = m_head;
}

//获取链表第一个有效节点
Span* SpanList::Begin()
{
	if (!m_head->next)
	{
		return nullptr;
	}

	return m_head->next;
}

//获取链表最后一个节点
Span* SpanList::End()
{
	if (!m_head)
	{
		return nullptr;
	}

	return m_head;
}

//判读链表是否为空
bool SpanList::Empty()
{
	return m_head->next == m_head;
}

//头插
void SpanList::PushFront(Span* span)
{
	assert(m_head);
	assert(span);

	m_head->next->prev = span;
	span->next = m_head->next;
	span->prev = m_head;
	m_head->next = span;

}

//头删
Span* SpanList::PopFront()
{
	assert(m_head);
	assert(m_head->next);
	
	Span* front = m_head->next;

	Erase(front);

	return front;
}

void SpanList::Erase(Span* pos)
{
	assert(pos);

	//pos->prev->next = pos->next;
	//pos->next->prev = pos->prev;
	Span* prev = pos->prev;
	Span* next = pos->next;
	prev->next = next;
	next->prev = prev;
}

// ============================ SpanList ============================